#===istalismanplugin===
# -*- coding: utf-8 -*-

#  Talisman plugin
#  ping_plugin.py

#  Initial Copyright © 2007 dimichxp <dimichxp@gmail.com>
#  Modifications Copyright © 2007 Als <Als@exploit.in>

#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.

#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.

ping_pending=[]
def handler_ping(type, source, parameters):
	nick=parameters
	groupchat=source[1]
	iq = xmpp.Iq('get')
	id = 'p'+str(random.randrange(1, 1000))
	globals()['ping_pending'].append(id)
	iq.setID(id)
	iq.addChild('query', {}, [], 'jabber:iq:version');
	if parameters:
		if GROUPCHATS.has_key(source[1]):
			nicks = GROUPCHATS[source[1]].keys()
			param = parameters.strip()
			if not nick in nicks:
				iq.setTo(param)
			else:
				if GROUPCHATS[groupchat][nick]['ishere']==0:
					reply(type, source, u'is he even here? :-O')
					return
				param=nick
				jid=groupchat+'/'+nick
				iq.setTo(jid)
	else:
		jid=groupchat+'/'+source[2]
		iq.setTo(jid)
		param=''
	t0 = time.time()
	JCON.SendAndCallForResponse(iq, handler_ping_answ,{'t0': t0, 'mtype': type, 'source': source, 'param': param})
	return


PINGBASE = {}

def handler_ping_log(jid, sec):
        dt = time.strftime('%d') +'.'+ time.strftime('%m') +'.'+ time.strftime('%Y')+' | '+time.strftime('%H') +':'+ time.strftime('%M') +':'+ time.strftime('%S')
        if not PINGBASE.has_key(jid):
                PINGBASE[jid] = {'pings':{}, 'min':sec, 'min_date':dt, 'max':sec, 'max_date':dt, 'average':0}
        if PINGBASE[jid]['min'] > sec:
                PINGBASE[jid]['min'] = sec
                PINGBASE[jid]['min_date'] = dt
        if PINGBASE[jid]['max'] < sec:
                PINGBASE[jid]['max'] = sec
                PINGBASE[jid]['max_date'] = dt
        PINGBASE[jid]['pings'][dt] = sec
        tmp = 0
        for AV in PINGBASE[jid]['pings']:
                tmp+= PINGBASE[jid]['pings'][AV]
        PINGBASE[jid]['average'] = tmp / len( PINGBASE[jid]['pings'] )



def handler_ping_answ(coze, res, t0, mtype, source, param):
	id = res.getID()
	inf = ''
	if id in globals()['ping_pending']:
		globals()['ping_pending'].remove(id)
	else:
		print 'someone is doing wrong...'
		return
	if res:
		if res.getType() == 'result':
			t = time.time()
			rep = u''
			second = round(t-t0, 3)
			if param:
				rep +=random.choice([u'pong from '+param+u' is', u'Response rate for the server '+param+u' is', u'The rate of sending packets from '+param+u' is', u'aha! What I dug up! This is Pong on '+param+':'])   
			else:
				rep += random.choice([u'Your pong is', u'Response rate is equal to the server for you', u'The rate of sending your ping', u'aha! What I dug up! This is your pong :'])
			rep+=u' '+str(second)+u' seconds'
			png = second
			handler_ping_log( get_true_jid(source[0]), second )
			if png < 0.10:
				if not param:
					inf = u'your net is really reactive!'
				else:
					inf = u'its a reactive net!'
			if  (png >= 0.10) & (png < 0.50):
				if not param:
					inf = u'you have a great pong!'
				else:
					inf = u'its a great pong!'
			if (png >= 0.50) & (png < 1.00):
				if not param:
					inf = u'a normal pong! GPRS, yes?!'
				else:
					inf = u'its very normal! GPRS?'
			if (png >= 1.00) & (png < 1.20):
				if not param:
					inf = u'your pong is normal, GPRS'
				else:
					inf = u'his is normal, GPRS'
			if (png >= 1.20) & (png < 1.60):
				if not param:
					inf = u'your net is slow, GPRS'
				else:
					inf = u'its a slow pong, GPRS'
			if (png >= 1.60) & (png < 2.00):
				if not param:
					inf = u'Your pong is very slow, GPRS'
				else:
					inf = u'his pong sucks, GPRS'
			if (png >= 2.00) & (png < 6.00):
				if not param:
					inf = u'you broke your pong, GPRS'
				else:
					inf = u'his pong broken, GPRS'
			if (png >= 6.00):
				if not param:
					inf = u'its up the wall'
				else:
					inf = u'its dead'
			rep = rep + ' - ' + inf
		else:
			rep = u'not pinging'
	reply(mtype, source, rep)

def handler_ping_stats(type, source, parameters):
        if parameters:
                if parameters in GROUPCHATS[source[1]].keys():
                        JID = GROUPCHATS[source[1]][parameters]['jid']
                else:
                        reply(type, source, u'hmmm?')
                        return
        else:
                JID = get_true_jid(source[0])
        if PINGBASE.has_key(JID):
                TEXT = u'\n•• Ping statistics [only %s] : \n• Shortest ping %s was recorded [%s] \n• Longest ping %s was recorded [%s] \n• Average length of ping : %s' % (str(len(PINGBASE[JID]['pings'])), str(PINGBASE[JID]['min']), str(PINGBASE[JID]['min_date']), str(PINGBASE[JID]['max']), str(PINGBASE[JID]['max_date']), str(round(PINGBASE[JID]['average'], 3)) )
        else:
                TEXT = u'you have not pinged so ask statistics ]:->'
        reply(type, source, TEXT)

TURBO_PING = {}
TURBO_LIM = {}

def handler_turbo_ping(t, s, p):
        global TURBO_PING
        global TURBO_LIM
        jid = s[1]+'/'+s[2]
        if p:
                if s[1] in GROUPCHATS and p in GROUPCHATS[s[1]]:
                        if p==get_bot_nick(s[1]):
                                reply(t, s, u'My Pong is canceled! And yours?')
                                return
                        jid = s[1]+'/'+p
                else:
                        jid = p
        i = s[1]+'/'+s[2]
        srv, rep = '', ''
        #if i in TURBO_PING.keys() and p=='??':
        #        reply(t, s, i+':\n'+'; '.join([str(x) for x in TURBO_PING[i]]))
        #        return
        if TURBO_PING:
                reply(t, s, u'Wait a minute!')
                return
        TURBO_LIM[jid]=time.time()
        TURBO_PING[jid]={'jid':[],'s2s':[],'bot':[]}
        reply(t, s, u'Testing started..')
        for x in range(20):
                tojid = jid
                if x in range(11, 16):
                        if jid.count('@'):
                                spl='@'
                                if jid.count('@conference.'):
                                        spl='@conference.'
                                tojid = jid.split(spl)[1]
                                if tojid.count('/'):
                                        tojid = tojid.split('/')[0]
                        srv = tojid
                if x in range(16, 21):
                        tojid = JID.split('@')[1]
                iq = xmpp.Iq('get')
                id = str(x)
                iq.setID(id)
                iq.setTo(tojid)
                iq.addChild('query', {}, [], 'jabber:iq:version');
                JCON.SendAndCallForResponse(iq, handler_turboping_answ,{'tt': time.time(), 'jid': jid})
                time.sleep(3)
        tt=time.time()
        while (len(TURBO_PING[jid]['jid'])+len(TURBO_PING[jid]['s2s'])+len(TURBO_PING[jid]['bot']))!=20:
                if time.time()-tt>120:
                        break
                time.sleep(1)
                pass
        if len(TURBO_PING[jid]['jid'])<3:
                reply(t, s, u'Pong worthless, or the address is not valid! Part of the package is lost!')
                return
        l = getMedian(TURBO_PING[jid]['jid'])
        bot = getMedian(TURBO_PING[jid]['bot'])
        s2s = getMedian(TURBO_PING[jid]['s2s']) - bot
        
        rep = u'\n•• Ping turbo : \n• Minimum '+str(min(TURBO_PING[jid]['jid']))+u'с. \n• Maximum '+str(max(TURBO_PING[jid]['jid']))+u'с. \n• Medium result '
        rep += u' of '+str(len(TURBO_PING[jid]['jid']))+u' queries '+str(round(l, 3))+u' с. \n'
        rep += u'• Botping '+str(bot)+u'c. \n'
        rep += u'• Pong from server '+JID.split('@')[1]+u' to the server '+srv+' '+str(round(s2s, 2))+u'c. \n'
        rep += u'• The result of taking into account all the parameters '+str(round((l-bot)-s2s, 3))+u' seconds.\n'
        res = (l-bot)-s2s
        rep +=u'• Rating pong on a scale of 0 to 5 '
        if res< 0.1: rep+=u' 5+'
        if res< 0.6 and res> 0.1: rep+=u' 5'
        if res<1.1 and res>0.5: rep+=u' 4'
        if res<2.2 and res>1: rep+=u' 3'
        if res<5.5 and res>2.1: rep+=u' 2'
        if res<8.8 and res>5.4: rep+=u' 1'
        if res>=8.8: rep+=u' 0'
        reply(t, s, rep)
        TURBO_PING.clear()
        
def handler_turboping_answ(cl, res, tt, jid):
        global TURBO_PING
        if res:
                if res.getType() == 'result':
                        t = time.time()
                        if int(res.getID()) in range(11, 16):
                                TURBO_PING[jid]['s2s'].append(round(t-tt, 3))
                                return
                        if int(res.getID()) in range(16, 21):
                                TURBO_PING[jid]['bot'].append(round(t-tt, 3))
                                return
                        TURBO_PING[jid]['jid'].append(round(t-tt, 3))

def getMedian(numericValues):
    theValues = sorted(numericValues)
    if len(theValues) % 2 == 1:
        return theValues[(len(theValues)+1)/2-1]
    else:
        lower = theValues[len(theValues)/2-1]
        upper = theValues[len(theValues)/2]
    return (float(lower + upper)) / 2
                        
register_command_handler(handler_turbo_ping, 'turboping', ['all'], 0, 'Ping checks of specified addresses in a minute, displays the median, maximum and minimum values.', 'turboping', ['turboping'])
register_command_handler(handler_ping_stats, 'pingstat', ['info','muc','all'], 0, 'displays ping statistics.', 'pingstat [nick]', ['pingstat guy','pingstat jabber.ru'])
register_command_handler(handler_ping, 'ping', ['info','muc','all'], 10, 'Pings you, or a specific server or nickname.', 'ping [nick]', ['ping guy','ping jabber.ru'])
